package com.yswy.app.res;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.volcengine.util.Sts2Utils;
import com.yswy.common.model.ResultModel;
import com.yswy.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * @author monkey
 * @desc 返回数据加密
 * @date 2018/10/25 20:17
 */
@ControllerAdvice(basePackages = "com.yswy.app.controller")
public class EncodeResponseBodyAdvice implements ResponseBodyAdvice {
    private final static Logger logger = LoggerFactory.getLogger(EncodeResponseBodyAdvice.class);

    private static final String CLIENT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7bPKLSwYMT5GmAXFbzGo3lYNeVsQQn6+3ulgXFKM0ZHeeUlaymf0PoxvBj32j0h8oVr8xNSvwZGJTF97Pe6fOzZG4lUE3iN8EakZoPmkY3PGtckEFsPcg960Ier4JynHg5OMEE5/Zm5FIhJ8gb37aU/NdxienOPkoDOO2prqQ+wIDAQAB";
    private static final String SERVER_PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALts8otLBgxPkaYBcVvMajeVg15WxBCfr7e6WBcUozRkd55SVrKZ/Q+jG8GPfaPSHyhWvzE1K/BkYlMX3s97p87NkbiVQTeI3wRqRmg+aRjc8a1yQQWw9yD3rQh6vgnKceDk4wQTn9mbkUiEnyBvftpT813GJ6c4+SgM47amupD7AgMBAAECgYAlDhQh3/JRKsYT+QMNcCur056GX0ciNkAKZggWgBkIObjAj2zeoL08gzXwncrsQZWxZv0j4GxQebhKz1RY1wzE6owumTADN8m4J5E8HWcFH7rW4AATpCgkmaOnutU3PF1gBVAqKyQFSENoJ8+RjdchKgbOyDFBYF0IIq9PnQsgsQJBAOJvkUkpf5pgiooTK1LT9EEValMJG5aah3mpMc6mB6rJ+j7evC6HZgodDBmC00i0jk8okl2MUjA6om8JBPQMqnkCQQDT5X6eaSbLuMg1kLe9s+AiO6Pl7BJna70enrYpR4YsIXFGP2fvkDbJuuGRgVCpCfnN07B1jBuG8rY53ydJ3roTAkBztREnsqX67BQ/JDaCN77btybC0aegWMyblaLW9y55zoYqtESy/gtdZaR2MMzonSMPPis01Gx3Kq8wUAqQ7xv5AkEAyM9Iu58zIQWw1vKa7rC0zDxxCsg6eMBlrcsDHwOlZ9UZoFUejq3A/lSYyGggpNHLZwAizoNE4xLJFvcgKKVm+QJBANi7+VNWOci2wLfgV42gQZCUEnJzA5PabmZuq6wIdGO5bn/4ehMWYD+65O3Y7lDcfmWGu1B4m9GQsL/x9mHp5ho=";

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        boolean encode = false;
        if (methodParameter.getMethod().isAnnotationPresent(SecurityParameter.class)) {
            //获取注解配置的包含和去除字段
            SecurityParameter serializedField = methodParameter.getMethodAnnotation(SecurityParameter.class);
            //出参是否需要加密
            encode = serializedField.outEncode();
        }
        if (encode) {
            logger.info("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行加密");
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(body);
                JSONObject jsonObject = JSONObject.parseObject(result);
                String s = jsonObject.getString("data");
                Map<String, String> map = new HashMap<>();
                if (StringUtils.isNotEmpty(s)){
                    // 生成aes秘钥
                    String aseKey = getRandomString(16);
                    // rsa加密
                    String encrypted = RSAUtils.encryptedDataOnJavaByPrivateKey(aseKey, SERVER_PRIVATE_KEY);
                    // aes加密
                    String requestData = AesEncryptUtils.encrypt(s, aseKey);

                    map.put("encrypted", encrypted);
                    map.put("requestData", requestData);
                    return  ResultModel.ok(map);
                }else {
                    return  ResultModel.ok();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("对方法method :【" + methodParameter.getMethod().getName() + "】返回数据进行解密出现异常：" + e.getMessage());
            }
        }
        return body;
    }

    /**
     * 创建指定位数的随机字符串
     *
     * @param length 表示生成字符串的长度
     * @return 字符串
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
}
